package common

import (
	"context"
	"fmt"
	"github.com/sirupsen/logrus"
	"os"
	"time"
)

/*
基于 Context 的日志使用方式：

 1. 使用 WithContext 创建日志记录器：
    logger := common.WithContext(c.Request.Context())
    logger.Info("这是一条日志")

 2. 带字段的日志记录：
    logger := common.WithContext(c.Request.Context())
    logger.WithFields(logrus.Fields{
    "method": c.Request.Method,
    "path":   c.Request.URL.Path,
    "ip":     c.ClientIP(),
    }).Error("请求处理错误")

注意：需要先调用 common.Logs() 方法初始化日志配置

需要添加中间件 在所有中间件最前面

	func RequestIdMiddleware() gin.HandlerFunc {
		return func(c *gin.Context) {
			// 为当前请求生成新的 requestId
			ctx := WithRequestId(c.Request.Context())

			// 更新请求的 context
			c.Request = c.Request.WithContext(ctx)

			c.Next()
		}
	}

就可以直接拿去 这个值了
currentId := common.GetRequestId(c.Request.Context())
*/

func Logs() {
	logrus.SetLevel(logrus.DebugLevel)
	logrus.SetReportCaller(true)
	logrus.SetFormatter(&logrus.JSONFormatter{
		TimestampFormat: time.RFC3339,
	})

	if _, err := os.Stat("logs"); os.IsNotExist(err) {
		_ = os.Mkdir("logs", 0755)
	}

	logFileName := fmt.Sprintf("logs/app-%s.log", time.Now().Format("2006-01-02"))
	logFile, err := os.OpenFile(logFileName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		fmt.Printf("Failed to open log file: %v\n", err)
	} else {
		logrus.SetOutput(logFile)
		logrus.AddHook(&LogsRequestId{})
	}
}

type LogsRequestId struct{}

func (hook *LogsRequestId) Levels() []logrus.Level {
	return logrus.AllLevels
}

func (hook *LogsRequestId) Fire(entry *logrus.Entry) error {
	if entry.Context != nil {
		if requestId := GetRequestId(entry.Context); requestId != "" {
			entry.Data["requestId"] = requestId
		}
	}
	return nil
}

type requestIdKey struct{}

func NewRequestId() string {
	return fmt.Sprintf("%d", time.Now().UnixNano()%9000000001+100000000000)
}

func WithRequestId(ctx context.Context) context.Context {
	return context.WithValue(ctx, requestIdKey{}, NewRequestId())
}

func GetRequestId(ctx context.Context) string {
	if v, ok := ctx.Value(requestIdKey{}).(string); ok {
		return v
	}
	return ""
}

type Logger struct {
	ctx context.Context
	log context.Context
}

func WithContext(ctx context.Context) *Logger {
	return &Logger{ctx: ctx}
}

//	logger.WithFields(logrus.Fields{
//					"method": c.Request.Method,
//					"path":   c.Request.URL.Path,
//					"ip":     c.ClientIP(),
//					"error":  err.Error(),
//				}).Error("请求处理错误")
func (l *Logger) WithFields(fields logrus.Fields) *logrus.Entry {
	return logrus.WithContext(l.ctx).WithFields(fields)
}

func (l *Logger) Info(args ...interface{}) {
	logrus.WithContext(l.ctx).Info(args...)
}

func (l *Logger) Infof(format string, args ...interface{}) {
	logrus.WithContext(l.ctx).Infof(format, args...)
}

func (l *Logger) Debug(args ...interface{}) {
	logrus.WithContext(l.ctx).Debug(args...)
}

func (l *Logger) Debugf(format string, args ...interface{}) {
	logrus.WithContext(l.ctx).Debugf(format, args...)
}

func (l *Logger) Warn(args ...interface{}) {
	logrus.WithContext(l.ctx).Warn(args...)
}

func (l *Logger) Warnf(format string, args ...interface{}) {
	logrus.WithContext(l.ctx).Warnf(format, args...)
}

func (l *Logger) Error(args ...interface{}) {
	logrus.WithContext(l.ctx).Error(args...)
}

func (l *Logger) Errorf(format string, args ...interface{}) {
	logrus.WithContext(l.ctx).Errorf(format, args...)
}

func (l *Logger) Fatal(args ...interface{}) {
	logrus.WithContext(l.ctx).Fatal(args...)
}

func (l *Logger) Fatalf(format string, args ...interface{}) {
	logrus.WithContext(l.ctx).Fatalf(format, args...)
}

func (l *Logger) Panic(args ...interface{}) {
	logrus.WithContext(l.ctx).Panic(args...)
}

func (l *Logger) Panicf(format string, args ...interface{}) {
	logrus.WithContext(l.ctx).Panicf(format, args...)
}
